
import { LGXEnums } from './sysenum.js'

import GlobalConst from './globalConst.js'
var global = GlobalConst.GlobalConst;


var radian2Degree = function (fRadian) {
    return ((fRadian * 180) / Math.PI);
}

var degree2Radian = function (degree) {
    return (degree * Math.PI) / 180.0;
}

class LGXPoint {
    constructor() {
        this.x = 0;
        this.y = 0;
    }

    clone(src) {
        this.x = src.x;
        this.y = src.y;
    }

    setVal(x, y) {
        this.x = x;
        this.y = y;
    }
}

class LGXRect {
    constructor(left, top, right, bottom) {
        this.left = left;
        this.right = right;
        this.top = top;
        this.bottom = bottom;
    }

    clone(src) {
        this.left = src.left;
        this.right = src.right;
        this.top = src.top;
        this.bottom = src.bottom;
    }

    expand(val) {
        this.left -= val;
        this.top += val;
        this.right += val;
        this.bottom -= val;
    }

    ltPt() {
        let pt = new LGXPoint();
        pt.setVal(this.left, this.top);
        return pt;
    }
    lbPt() {
        let pt = new LGXPoint();
        pt.setVal(this.left, this.bottom);
        return pt;
    }
    rtPt() {
        let pt = new LGXPoint();
        pt.setVal(this.right, this.top);
        return pt;
    }
    rbPt() {
        let pt = new LGXPoint();
        pt.setVal(this.right, this.bottom);
        return pt;
    }

    width() { return (Math.abs(this.right - this.left)); }
    height() { return (Math.abs(this.bottom - this.top)); }
    area() { return (this.width() * this.height()); }

    contains(x, y) { return (this.left <= x && x <= this.right) && (this.bottom <= y && y <= this.top); }
    ptInRect(pt) {
        return this.posInRect(pt.x, pt.y);
    }

    posInRect(x, y) {
        var gap1 = x - this.left;
        var gap2 = this.right - x;
        var gap3 = y - this.bottom;
        var gap4 = this.top - y;
        var flag = false;
        if ((gap1 >= 0 || Math.abs(gap1) < global.ZERO_4E)
            && (gap2 >= 0 || Math.abs(gap2) < global.ZERO_4E)
            && (gap3 >= 0 || Math.abs(gap3) < global.ZERO_4E)
            && (gap4 >= 0 || Math.abs(gap4) < global.ZERO_4E)
        ) {
            flag = true;
        }
        return flag;
    }

    getCnt() {
        var x = (this.left + this.right) * 0.5;
        var y = (this.top + this.bottom) * 0.5;
        return { x, y };
    }

    convert4Pt2List() {
        let list = [];
        list.push(this.ltPt());
        list.push(this.rtPt());
        list.push(this.rbPt());
        list.push(this.lbPt());
        return list;
    }

}

class LXSize {
    constructor() {
        this.w = 0;
        this.h = 0;
    }
}

//图形修改相关控制信息
class LXModifyCMDInfo {
    constructor() {
        this.scaling = 1;//当前显示比例
        this.mapscale = 1;//全局缩放比例
        this.shiftdown = false;//shift键是否按下
        this.ctrldown = false;//ctrl键是否按下
    }

    clone(src) {
        this.scaling = src.scaling;
        this.mapscale = src.mapscale;
        this.shiftdown = src.shiftdown;
        this.ctrldown = src.ctrldown;
    }
}

class LGXColor {
    constructor() {
        this.alpha = 255;
        this.red = 255;
        this.green = 255;
        this.blue = 255;
    }

    setVal(r, g, b, a = 255) {
        this.alpha = a;
        this.red = r;
        this.green = g;
        this.blue = b;
    }


    setColorByValue(rgbaVal) {
        this.red = rgbaVal & 0x000000ff;
        this.green = (rgbaVal & 0x0000ff00) >> 8;
        this.blue = (rgbaVal & 0x00ff0000) >> 16;
        this.alpha = 255;//(rgbaVal & 0xff000000) >> 24;
    }

    clone(src) {
        this.alpha = src.alpha;
        this.red = src.red;
        this.green = src.green;
        this.blue = src.blue;
    }

    getCloneCopy() {
        let ret = new LGXColor();
        ret.alpha = this.alpha;
        ret.red = this.red;
        ret.green = this.green;
        ret.blue = this.blue;
        return ret;
    }

    toValue() {
        var val = this.alpha;
        var g = this.green;
        var b = this.blue;
        val = (val << 24) | (b << 16) | (g << 8) | this.red;
        return val;
    }

    invert() {
        let intertColor = new LGXColor();
        intertColor.red = 255 - this.red;
        intertColor.green = 255 - this.green;
        intertColor.blue = 255 - this.blue;
        intertColor.alpha = this.alpha;
        return intertColor;
    }

    toHexString() {
        var reds = this.red.toString(16);
        if (reds.length == 1) {
            reds = "0" + reds;
        }
        var greens = this.green.toString(16);
        if (greens.length == 1) {
            greens = "0" + greens;
        }
        var blues = this.blue.toString(16);
        if (blues.length == 1) {
            blues = "0" + blues;
        }
        var alphas = this.alpha.toString(16);
        if (alphas.length == 1) {
            alphas = "0" + alphas;
        }
        // var colors = "#" + reds + greens + blues+alphas;
        var colors = "#" + reds + greens + blues;
        return colors;
    }

    //"(red,green,blue,alpha)"
    setByHexString(strVal) {
        if (strVal.length != 7 && strVal.length != 9) {
            console.log("error color format***********************");
            return;
        }
        var sharpCh = strVal.substr(0, 1);
        if (sharpCh != "#") {
            return;
        }
        let strRed = strVal.substr(1, 2);
        let strGreen = strVal.substr(3, 2);
        let strBlue = strVal.substr(5, 2);
        this.red = parseInt(strRed, 16);
        this.green = parseInt(strGreen, 16);
        this.blue = parseInt(strBlue, 16);
        return;
    }

    setByRGBString(strVal) {
        strVal = strVal.replace(/\s/g, "");
        strVal = strVal.replace(/[\n\r]/g, "");
        strVal = strVal.toUpperCase();
        var headStr = strVal.substr(0, 3);
        if (headStr != "RGB") {
            return;
        }
        let validLen = strVal.length - 5;
        let validStr = strVal.substr(4, validLen);
        let strList = validStr.split(",");
        let strRed = strList[0];
        let strGreen = strList[1];
        let strBlue = strList[2];
        let dec = 10;
        if (strVal.indexOf("X") >= 0) {
            dec = 16;
        }
        this.red = parseInt(strRed, dec);
        this.green = parseInt(strGreen, dec);
        this.blue = parseInt(strBlue, dec);
        return;
    }

    setHtmlColor(val) {
        if (val.indexOf('#') >= 0) {
            this.setByHexString(val);
        }
        else if (val.indexOf('rgb') >= 0) {
            this.setByHexString(val);
        }
    }
}

class LGXLineDefInfo {
    constructor() {
        this.linemode = LGXEnums.LGXLineMode.Solid;
        this.joinmode = LGXEnums.LGXLineJoin.Bevel;
        this.capmode = LGXEnums.LGXLineCap.Flat;
        this.lineWidth = 0;
        this.stArrowType = "none";
        this.endArrowType = "none";
        this.color = new LGXColor();
    }

    clone(src) {
        this.linemode = src.linemode;
        this.joinmode = src.joinmode;
        this.capmode = src.capmode;
        this.lineWidth = src.lineWidth;
        this.color.clone(src.color);
        this.stArrowType = src.stArrowType;
        this.endArrowType = src.endArrowType;
    }

    setModeByDesc(desc) {
        if (desc == 'none') {
            this.linemode = LGXEnums.LGXLineMode.NoPen;
        }
        else if (desc == 'solid') {
            this.linemode = LGXEnums.LGXLineMode.Solid;
        }
        else if (desc == 'dashline') {
            this.linemode = LGXEnums.LGXLineMode.Dash_Dash;
        }
    }
    toJson() {
        let obj = {};
        obj["mode"] = this.linemode;
        obj["width"] = this.lineWidth;
        obj["join"] = this.joinmode;
        obj["cap"] = this.capmode;
        obj["stArrow"] = this.stArrowType;
        obj["endArrow"] = this.endArrowType;
        obj["color"] = this.color.toValue();
        return obj;
    }
    fromJson(obj) {
        this.linemode = obj["mode"];
        this.lineWidth = obj["width"];
        this.joinmode = obj["join"];
        this.capmode = obj["cap"];
        this.stArrowType = obj["stArrow"];
        this.endArrowType = obj["endArrow"];
        let t = obj["color"];
        this.color.setColorByValue(t);
    }
}


class LGXLineSection {
    constructor() {
        this.stPt = new LGXPoint();
        this.endPt = new LGXPoint();
        this.lenth = 0;
        this.vector = new LGXVector();
    }

    setPt(p1, p2) {
        this.stPt.x = p1.x;
        this.stPt.y = p1.y;
        this.endPt.x = p2.x;
        this.endPt.y = p2.y;
        this.vector.setBy2Pt(p1, p2);
        this.calLenth();
    }

    calLenth() {
        var dx = this.stPt.x - this.endPt.x;
        var dy = this.stPt.y - this.endPt.y;
        this.lenth = Math.sqrt(dx * dx + dy * dy);
    }
}

//向量
class LGXVector {
    constructor() {
        this.m = 1;
        this.n = 0;
        this.p = 0;
    }

    setValue(m, n, p = 0) {
        this.m = m;
        this.n = n;
        this.p = p;
        this.identity();
        this.m = this.evaluate(this.m);
        this.n = this.evaluate(this.n);
        this.p = this.evaluate(this.p);
    }
    setBy2Pt(p1, p2) {
        if (p1 == null || p2 == null) {
            console.log('eeor');
        }
        this.m = p2.x - p1.x;
        this.n = p2.y - p1.y;
        this.p = 0;
        this.identity();
        this.m = this.evaluate(this.m);
        this.n = this.evaluate(this.n);
        this.p = this.evaluate(this.p);
    }

    setByAngleDegree(angle) {
        let rad = Math.PI * angle / 180.0;
        this.m = Math.cos(rad);
        this.n = Math.sin(rad);
        this.p = 0;
    }

    invert() {
        this.m = -1 * this.m;
        this.n = -1 * this.n;
        this.p = -1 * this.p;
    }

    invertCopy() {
        var dst = new LGXVector();
        dst.m = -1 * this.m;
        dst.n = -1 * this.n;
        dst.p = -1 * this.p;
        return dst;
    }

    mod() {
        var temp = this.m * this.m + this.n * this.n + this.p * this.p;
        return Math.sqrt(temp);
    }

    rotate(degree) {
        var theta = degree2Radian(degree);
        var a = this.m * Math.cos(theta) - this.n * Math.sin(theta);
        var b = this.m * Math.sin(theta) + this.n * Math.cos(theta);
        this.identity();
        this.m = this.evaluate(a);
        this.n = this.evaluate(b);
    }

    rotateCopy(degree) {
        var dst = this.cloneCopy();
        dst.rotate(degree);
        return dst;
    }

    //当前向量和目标向量间的夹角
    angleToAnotherVector_Degree(vect) {
        //平面向量夹角公式：cos=(ab的内积)/(|a||b|)
        var degree = 0;
        var cosval = Math.abs(this.m * vect.m + this.n * vect.n);
        if (cosval > 1) {
            cosval = 1;
        }
        if (cosval < global.ZERO_4E) {
            degree = 90;
        }
        else {
            var theta = Math.acos(cosval);
            degree = radian2Degree(theta);
        }
        return degree;
    }
    //当前向量到目标向量的旋转角
    angleByCrossMultiply2Another(vect) {
        //设A=a + b*i
        //  B=c + d*i;
        //向量乘积公式：A^X=B
        //==> X=B/A=(c + d*i)/(a + b*i) = (c + d*i)*(a - b*i)/(a*a + b*b)
        //=(a*c + d*b) + (d*a - c*b)*i
        //(a*c - d*b)为实部，(d*a - c*b)为虚部
        //由于向量都做了归一化，所以（a*a + b*b）恒等于1

        var a = this.m;
        var b = this.n;
        var c = vect.m;
        var d = vect.n;

        var temp1 = a * c + d * b;
        var temp2 = d * a - c * b;

        var degree = 0;
        if (Math.abs(temp1) < global.ZERO_8E) {
            if (temp2 > 0) {
                degree = 90;
            }
            else {
                degree = 270;
            }
        }
        else {
            if (Math.abs(temp2) < global.ZERO_8E) {
                if (temp1 > 0) {
                    degree = 0;
                }
                else {
                    degree = 180;
                }
            }
            else {
                var theta = Math.atan(temp2 / temp1);
                degree = radian2Degree(theta);
                if (temp1 > 0) {
                    //1 4 象限
                    if (temp2 < 0) {
                        degree = 360 + degree;
                    }
                }
                else if (temp1 < 0) {
                    //2 3 象限
                    degree = 180 + degree;
                }
            }
        }
        return degree;
    }

    //当前向量以X轴正向计算得到的旋转角
    angleFrmXAxisPositiveDir() {
        var XAxisPositiveVector = new LGXVector;
        XAxisPositiveVector.setValue(1, 0, 0);
        //设A=a + b*i
        //  B=c + d*i;
        //向量乘积公式：A^X=B
        //==> X=B/A=(c + d*i)/(a + b*i) = (c + d*i)*(a - b*i)/(a*a + b*b)
        //=(a*c + d*b) + (d*a - c*b)*i
        //(a*c - d*b)为实部，(d*a - c*b)为虚部
        //由于向量都做了归一化，所以（a*a + b*b）恒等于1

        var a = XAxisPositiveVector.m;
        var b = XAxisPositiveVector.n;
        var c = this.m;
        var d = this.n;

        var temp1 = a * c + d * b;
        var temp2 = d * a - c * b;

        var degree = 0;
        if (Math.abs(temp1) < global.ZERO_8E) {
            if (temp2 > 0) {
                degree = 90;
            }
            else {
                degree = 270;
            }
        }
        else {
            if (Math.abs(temp2) < global.ZERO_8E) {
                if (temp1 > 0) {
                    degree = 0;
                }
                else {
                    degree = 180;
                }
            }
            else {
                var theta = Math.atan(temp2 / temp1);
                degree = radian2Degree(theta);
                if (temp1 > 0) {
                    //1 4 象限
                    if (temp2 < 0) {
                        degree = 360 + degree;
                    }
                }
                else if (temp1 < 0) {
                    //2 3 象限
                    degree = 180 + degree;
                }
            }
        }
        return degree;
    }

    clone(src) {
        this.m = src.m;
        this.n = src.n;
        this.p = src.p;
    }
    cloneCopy() {
        var dst = new LGXVector();
        dst.clone(this);
        return dst;
    }

    //平行
    parallel(other) {
        let includeAngle = this.angleToAnotherVector_Degree(other);
        if (includeAngle < global.ZERO_8E) {
            return true;
        }
        return false;
    }
    //垂直
    perpendicular(other) {
        let includeAngle = this.angleToAnotherVector_Degree(other);
        if ((90 - includeAngle) < global.ZERO_8E) {
            return true;
        }
        return false;
    }

    //相等
    equal(other) {
        let rotAngle1 = this.angleByCrossMultiply2Another(other);
        let rotAngle2 = other.angleByCrossMultiply2Another(this);
        if (Math.abs(rotAngle1) < global.ZERO_8E || Math.abs(rotAngle2) < global.ZERO_8E) {
            return true;
        }
        return false;
    }

    identity() {
        var nMode = Math.sqrt(this.m * this.m + this.n * this.n + this.p * this.p);
        this.m = this.m / nMode;
        this.n = this.n / nMode;
        this.p = this.p / nMode;
    }

    evaluate(m) {
        if (Math.abs(m) < global.ZERO_8E) {
            m = 0;
        }
        else if (Math.abs(m - 1) < global.ZERO_8E) {
            m = 1;
        }
        else if (Math.abs(m + 1) < global.ZERO_8E) {
            m = -1;
        }
        return m;
    }

    //
    crossMultiply(src) {
        let ax = this.m;
        let ay = this.n;
        let az = this.p;

        let bx = src.m;
        let by = src.n;
        let bz = src.p;

        let c1 = ay * bz - az * by;
        let c2 = az * bx - ax * bz;
        let c3 = ax * by - ay * bx;
        let dstVct = new LGXVector();
        dstVct.setValue(c1, c2, c3);
        return dstVct;
    }

    dotMultiply(src) {
        //已经归一化，所以不需要再做取模运算
        let ret = this.m * src.m + this.n * src.n + this.p * src.p;
        return ret;
    }

    //0--非横平竖直线
    //1--水平线
    //2--垂直线
    getHornVertKind() {
        let kind = 0;
        let degree = this.angleFrmXAxisPositiveDir();
        if ((Math.abs(degree) < global.ZERO_4E)
            || (Math.abs(degree - 180) < global.ZERO_4E)
            || (Math.abs(degree - 360) < global.ZERO_4E)) {
            kind = 1;
        }
        else if ((Math.abs(degree - 90) < global.ZERO_4E)
            || (Math.abs(degree - 270) < global.ZERO_4E)) {
            kind = 2;
        }
        return kind;
    }
}

class LGXRayLine {
    constructor() {
        this.stPt = new LGXPoint();
        this.vector = new LGXVector();
        this.color = new LGXColor();
        this.color.setVal(128, 0, 0);
        this.lineWidth = 1;
        this.display = 0;

    }

    setPt(p1, p2) {
        this.stPt.clone(p1);
        this.vector.setBy2Pt(p1, p2);
    }
}

class LGXMarkingLine {
    constructor() {
        this.stPt = new LGXPoint();
        this.endPt = new LGXPoint();

        this.color = new LGXColor();
        this.color.setVal(128, 255, 0);
        this.lineWidth = 1;
        this.display = 0;
    }

    setPt(p1, p2) {
        this.stPt.x = p1.x;
        this.stPt.y = p1.y;
        this.endPt.x = p2.x;
        this.endPt.y = p2.y;
    }
}

class LGXFontInfo {
    constructor() {
        this.linedspace = 0;        // 行间距
        this.fontsize = 18;         // 字号
        this.fontFamily = "仿宋";     // 字体

        this.bold = false;			// 粗体
        this.italic = false;		// 倾斜
        this.underline = false;		// 带下划线
        this.fontStrikeout = false;		// 中间有直线通过的文本
        this.useBKFlag = false;         //是否使用底纹颜色
        this.fontColor = new LGXColor();     //文本颜色
        this.fontBKColor = new LGXColor();   //文本底纹颜色
    }
    clone(src) {
        this.linedspace = src.linedspace;        // 行间距
        this.fontsize = src.fontsize;         // 字号
        this.fontFamily = src.fontFamily;     // 字体
        this.bold = src.bold;			// 粗体
        this.italic = src.italic;		// 倾斜
        this.underline = src.underline;		// 带下划线
        this.fontStrikeout = src.fontStrikeout;		// 中间有直线通过的文本
        this.useBKFlag = src.useBKFlag;         //是否使用底纹颜色
        this.fontColor.clone(src.fontColor);     //文本颜色
        this.fontBKColor.clone(src.fontBKColor);   //文本底纹颜色
    }
}

export default {
    LGXRect, LGXPoint, LXSize, LXModifyCMDInfo, LGXColor,
    LGXLineDefInfo, LGXLineSection,
    LGXVector, LGXFontInfo, LGXRayLine, LGXMarkingLine
}
